home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-I386 / SEMAPHOR.{1G < prev    next >
Text File  |  1999-09-17  |  4KB  |  150 lines

  1. #ifndef _I386_SEMAPHORE_H
  2. #define _I386_SEMAPHORE_H
  3.  
  4. #include <linux/linkage.h>
  5.  
  6. /*
  7.  * SMP- and interrupt-safe semaphores..
  8.  *
  9.  * (C) Copyright 1996 Linus Torvalds
  10.  *
  11.  * Modified 1996-12-23 by Dave Grothe <dave@gcom.com> to fix bugs in
  12.  *                     the original code and to make semaphore waits
  13.  *                     interruptible so that processes waiting on
  14.  *                     semaphores can be killed.
  15.  * Modified 1999-02-14 by Andrea Arcangeli, split the sched.c helper
  16.  *               functions in asm/sempahore-helper.h while fixing a
  17.  *               potential and subtle race discovered by Ulrich Schmid
  18.  *               in down_interruptible(). Since I started to play here I
  19.  *               also implemented the `trylock' semaphore operation.
  20.  *
  21.  * If you would like to see an analysis of this implementation, please
  22.  * ftp to gcom.com and download the file
  23.  * /pub/linux/src/semaphore/semaphore-2.0.24.tar.gz.
  24.  *
  25.  */
  26.  
  27. #include <asm/system.h>
  28. #include <asm/atomic.h>
  29. #include <asm/spinlock.h>
  30.  
  31. struct semaphore {
  32.     atomic_t count;
  33.     int waking;
  34.     struct wait_queue * wait;
  35. };
  36.  
  37. #define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, NULL })
  38. #define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, NULL })
  39.  
  40. asmlinkage void __down_failed(void /* special register calling convention */);
  41. asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
  42. asmlinkage int  __down_failed_trylock(void  /* params in registers */);
  43. asmlinkage void __up_wakeup(void /* special register calling convention */);
  44.  
  45. asmlinkage void __down(struct semaphore * sem);
  46. asmlinkage int  __down_interruptible(struct semaphore * sem);
  47. asmlinkage int  __down_trylock(struct semaphore * sem);
  48. asmlinkage void __up(struct semaphore * sem);
  49.  
  50. extern spinlock_t semaphore_wake_lock;
  51.  
  52. #define sema_init(sem, val)    atomic_set(&((sem)->count), (val))
  53.  
  54. /*
  55.  * This is ugly, but we want the default case to fall through.
  56.  * "down_failed" is a special asm handler that calls the C
  57.  * routine that actually waits. See arch/i386/lib/semaphore.S
  58.  */
  59. extern inline void down(struct semaphore * sem)
  60. {
  61.     __asm__ __volatile__(
  62.         "# atomic down operation\n\t"
  63. #ifdef __SMP__
  64.         "lock ; "
  65. #endif
  66.         "decl 0(%0)\n\t"
  67.         "js 2f\n"
  68.         "1:\n"
  69.         ".section .text.lock,\"ax\"\n"
  70.         "2:\tpushl $1b\n\t"
  71.         "jmp __down_failed\n"
  72.         ".previous"
  73.         :/* no outputs */
  74.         :"c" (sem)
  75.         :"memory");
  76. }
  77.  
  78. extern inline int down_interruptible(struct semaphore * sem)
  79. {
  80.     int result;
  81.  
  82.     __asm__ __volatile__(
  83.         "# atomic interruptible down operation\n\t"
  84. #ifdef __SMP__
  85.         "lock ; "
  86. #endif
  87.         "decl 0(%1)\n\t"
  88.         "js 2f\n\t"
  89.         "xorl %0,%0\n"
  90.         "1:\n"
  91.         ".section .text.lock,\"ax\"\n"
  92.         "2:\tpushl $1b\n\t"
  93.         "jmp __down_failed_interruptible\n"
  94.         ".previous"
  95.         :"=a" (result)
  96.         :"c" (sem)
  97.         :"memory");
  98.     return result;
  99. }
  100.  
  101. extern inline int down_trylock(struct semaphore * sem)
  102. {
  103.     int result;
  104.  
  105.     __asm__ __volatile__(
  106.         "# atomic interruptible down operation\n\t"
  107. #ifdef __SMP__
  108.         "lock ; "
  109. #endif
  110.         "decl 0(%1)\n\t"
  111.         "js 2f\n\t"
  112.         "xorl %0,%0\n"
  113.         "1:\n"
  114.         ".section .text.lock,\"ax\"\n"
  115.         "2:\tpushl $1b\n\t"
  116.         "jmp __down_failed_trylock\n"
  117.         ".previous"
  118.         :"=a" (result)
  119.         :"c" (sem)
  120.         :"memory");
  121.     return result;
  122. }
  123.  
  124. /*
  125.  * Note! This is subtle. We jump to wake people up only if
  126.  * the semaphore was negative (== somebody was waiting on it).
  127.  * The default case (no contention) will result in NO
  128.  * jumps for both down() and up().
  129.  */
  130. extern inline void up(struct semaphore * sem)
  131. {
  132.     __asm__ __volatile__(
  133.         "# atomic up operation\n\t"
  134. #ifdef __SMP__
  135.         "lock ; "
  136. #endif
  137.         "incl 0(%0)\n\t"
  138.         "jle 2f\n"
  139.         "1:\n"
  140.         ".section .text.lock,\"ax\"\n"
  141.         "2:\tpushl $1b\n\t"
  142.         "jmp __up_wakeup\n"
  143.         ".previous"
  144.         :/* no outputs */
  145.         :"c" (sem)
  146.         :"memory");
  147. }
  148.  
  149. #endif
  150.